#!/usr/bin/tclsh
#
# +-------------------------------------------------------------------------+
# | e-vigr: ekt's - Virtual Infrastructure GReen meteR			    |
# | Copyright (C) 2010 National Documentation Center/NHRF ekt.vigr@gmail.com|
# |                                                                         |
# | This program is free software; you can redistribute it and/or           |
# | modify it under the terms of the GNU General Public License             |
# | as published by the Free Software Foundation; either version 2          |
# | of the License, or (at your option) any later version.                  |
# |                                                                         |
# | This program is distributed in the hope that it will be useful,         |
# | but WITHOUT ANY WARRANTY; without even the implied warranty of          |
# | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           |
# | GNU General Public License for more details.                            |
# +-------------------------------------------------------------------------+
# | This code is designed, written, and maintained by the EKT/NHRF.         |
# +-------------------------------------------------------------------------+
# | http://code.google.com/p/e-vigr/                                        |
# +-------------------------------------------------------------------------+
#
# Set folder for storing temporary files/program state
set TMP "./EPOWER"
# set initial configuration parameters
set ILOM_IP(0) 172.16.100.30
set ILOM_IP(1) 172.16.100.31
set VI_HOST(0) forked.domain.tld
set VI_HOST(1) path.domain.tld
set DOMAIN domain.tld

set TOTAL_VINFRA_WATT 0
set Proj_Cons 0
#set OID_VINFRA_WATT  .1.3.6.1.4.1.42.2.70.101.1.1.8.1.4.210; ILOM 2.0
set OID_VINFRA_WATT .1.3.6.1.4.1.42.2.70.101.1.1.8.1.4.196

set OID_VMs_IDs .1.3.6.1.4.1.8072.1.3.1.4.4.1.2.12.120.101.110.118.109.115.95.110.117.109.105.100
set OID_VMs_MEM .1.3.6.1.4.1.8072.1.3.1.3.4.1.2.10.120.101.110.118.109.115.95.109.101.109
set OID_VMs_CPU .1.3.6.1.4.1.8072.1.3.1.2.4.1.2.10.120.101.110.118.109.115.95.99.112.117
set OID_VMs_HOST .1.3.6.1.4.1.8072.1.3.1.1.4.1.2.11.120.101.110.118.109.115.95.110.97.109.101

set VINFRA_WATT 210000
set MAX_VINFRA_HOSTS 2
set EURO 0.0864
# DEI for B2 gives 0.03915, energy.eu gives 0.0725 - 0.0864 <500kw for full cost of electricity in Greece
set CO2_per_KWh 1000

#######################################################################
#power_per_vm:Estimate projected power consumption per Virtual Machine#
#######################################################################
proc power_per_vm { vm_id xen_host } {
		
	global DOMAIN
	global OID_VMs_CPU
	global OID_VMs_MEM
	global OID_VMs_HOST


	# puts "+++++++ $vm_id +++++ $xen_host"
 	set cpus [exec snmpget -m ALL  -v2c -c public $xen_host $OID_VMs_CPU.$vm_id -O qv]
	set mem  [exec snmpget -m ALL  -v2c -c public $xen_host $OID_VMs_MEM.$vm_id -O qv]
	set host_name  [exec snmpget -m ALL  -v2c -c public $xen_host $OID_VMs_HOST.$vm_id -O qv | cut -f 1]

	# puts "\t VM is: $host_name, CPUs: $cpus, MEM: $mem"

	if {[catch {exec snmpwalk -t 1 -v2c -c public $host_name.$DOMAIN hrProcessorLoad -O qv} Load]} {
	#"PROBLEM with $host_name SNMP $Load"
		set Load 1
	}

	set Load_Proc [split $Load]
	set Total_Load 0

	foreach proc $Load_Proc	{
		if {[catch {expr $proc + $Total_Load} Total_Load]}	{	
			return 210;
		} 
	}

	set Total_Load [expr 1.0*$Total_Load/[llength $Load_Proc]]
	set Power [expr 210 + $Total_Load/100.0*80]
	
	# puts "\t\tPower=$Power, Total_Load=$Total_Load, Load_Proc=$Load_Proc,Load=$Load"

    	return $Power
}
#walK through all the virtual infrastructure physical hosts
for {set i 0} {$i <$MAX_VINFRA_HOSTS} {incr i}  {
	#puts "$ILOM_IP($i) $OID_VINFRA_WATT";

	if {$i!=0} {
		set OID_VINFRA_WATT .1.3.6.1.4.1.42.2.70.101.1.1.8.1.4.196
	} else {
		set OID_VINFRA_WATT .1.3.6.1.4.1.42.2.70.101.1.1.8.1.4.172
	}
	

	if {[catch  {set VINFRA_WATT [exec /usr/bin/snmpget -m / -v2c -c public $ILOM_IP($i) $OID_VINFRA_WATT -O qv]} err ]} {
		puts "ERROR $i $err"
		exec mail -s "Power Monitoring script:$err" admin@domain.tld << $err;
	};

	#puts "XEN id $i: $VINFRA_WATT"
	#puts "/usr/bin/snmpget -m / -v2c -c public $ILOM_IP($i) $OID_VINFRA_WATT -O qv"
	#puts "IDS $i: snmpwalk -m ALL  -v2c -c public $VI_HOST($i) $OID_VMs_IDs -O qv"


	if {[ catch {set VMs_IDs_String($i) [exec snmpwalk -m ALL  -v2c -c public $VI_HOST($i) $OID_VMs_IDs -O qv] } err ]} {
		puts "ERROR $i $err"
		exec mail -s "Power Monitoring script:$err" admin@domain.tld << $err
		continue;	
	}

	set VMs_list($i) [split $VMs_IDs_String($i)]

	#puts "VMs_IDs_String $i: [string trim $VMs_IDs_String(0) \u000C ]"
	#puts "VMs_IDs_String $i: [string trim $VMs_IDs_String(0) \" ]"
	#puts "VMs_IDs_list $i: [string trim $VMs_list($i) \" ]"
	
	foreach item $VMs_list($i) {
		set num_item [string trim $item \"]
		if { $num_item > 0} {
			set vm_power [power_per_vm $num_item $VI_HOST($i)];
			set Proj_Cons [expr $Proj_Cons +$vm_power];
		} else {
			puts "No VMs on host $VI_HOST($i)"
			set vm_power 0;
			set Proj_Cons 0;
			continue;
		}
		#puts "\t Item: $num_item \tServer: $VI_HOST($i)"
		#puts "\t $vm_power $Proj_Cons"
        }

	#puts "TOTAL_VINFRA_WATT $TOTAL_VINFRA_WATT and $VINFRA_WATT";
	set TOTAL_VINFRA_WATT [expr $TOTAL_VINFRA_WATT+$VINFRA_WATT];

}

#Calculate basic power consumption figures
set TOTAL_VINFRA_WATT [expr $TOTAL_VINFRA_WATT/1000]
set Power_Gained [expr $Proj_Cons - $TOTAL_VINFRA_WATT]
set Percentage_Gained [expr 100.0*$Power_Gained/$Proj_Cons]

puts "Virtualization Platform Consumption $TOTAL_VINFRA_WATT W"
puts "Projected power consumption: $Proj_Cons"
puts "Total power gained: $Power_Gained"
puts "Power reduction percent: $Percentage_Gained %"

set chan [open $TMP/kwh_gained.xen.txt r]
set line [gets $chan]
set time_var [lindex $line 0]
set kwh_var [lindex $line 1]
close $chan

#Measure the energy gained in the period during the last script run
#read the previous run time, calculate time difference and energy gained
#write the new timestamp
set cur_time [clock seconds]
set pass_time [expr $cur_time - $time_var]
set hours_pass [expr $pass_time/3600.0]
set kwh_new [expr $kwh_var + $Power_Gained*$hours_pass/1000.0]
set total_kwh [list $kwh_new [expr $kwh_new*1.5] [expr $kwh_new*2.0] [expr $kwh_new*2.5]]
set total_co2 {}
set total_euro {}

#Calculate figures for different PUE values
foreach j $total_kwh	{
	#puts "$j"	
	lappend total_co2 [expr $j/$CO2_per_KWh] 
	lappend total_euro [expr $j*$EURO] 
}
#puts "Total kwh: $total_kwh \n Total CO2: $total_co2 \n Total E: $total_euro" 

#puts "percentage:$Percentage_Gained watts_gained:$Power_Gained total_watt:$TOTAL_VINFRA_WATT power_cons:$Proj_Cons"
#puts "Previous time is:$time_var Previous KWh:$kwh_var Current Time:$cur_time,Passed Time:$pass_time Hours Passed:$hours_pass New KWh saved:$kwh_new"


#EXPORT VALUES TO TEMPORARY FILES
set chan [open $TMP/kwh_gained.xen.txt w]
#puts $chan "$cur_time $kwh_new"
close $chan


set chan [open $TMP/pwr_cacti.xen.txt w]

#puts -nonewline $chan "percentage:$Percentage_Gained watts_gained:$Power_Gained total_watt:$TOTAL_VINFRA_WATT power_cons:$Proj_Cons "
set i 0
foreach val $total_kwh	{
	#puts -nonewline $chan "total_kwh_pue_$i:$val "
	incr i
}
set i 0
foreach val $total_co2  {
        #puts -nonewline $chan "total_kwh_co2_$i:$val "
        incr i
}
set i 0
foreach val $total_euro  {
        #puts -nonewline $chan "total_kwh_euro_$i:$val "
        incr i
}
close $chan

